﻿
using System;
using System.Collections.Generic;

namespace MyControl {

  #region 树结构工具类
  /// <summary>
  /// 树结构工具类
  /// </summary>
  #endregion
  class TreeUtils {

	#region 格式化数据回调函数
	/// <summary>
	/// 格式化数据回调函数
	/// </summary>
	/// <typeparam name="Data">要格式化的数据类型</typeparam>
	/// <param name="tree">当前索引项</param>
	/// <param name="index">当前索引序号</param>
	/// <param name="list">当前列表</param>
	/// <returns>格式化后的数据</returns>
	#endregion
	public delegate Data DataFormatBack<Data>(Tree tree, int index, List<Tree> list);

	#region 按需要取节点
	/// <summary>
	/// 按需要取节点
	/// </summary>
	/// <param name="treeList">数据列表</param>
	/// <param name="indexList">序号列表</param>
	/// <returns></returns>
	#endregion
	public static Tree FindTreeByIndex(List<Tree> treeList, List<int> indexList) {
	  if (indexList == null) {
		return null;
	  }
	  // 获取序号信息
	  var count = indexList.Count;
	  if (count == 0) {
		return null;
	  }
	  try {
		// 初始数据
		Tree findTree = treeList[indexList[0]];
		// 根据序号往下寻找数据
		for (int i = 1; i < count; i++) {
		  var index = indexList[i];
		  findTree = findTree.Children[index];
		}
		return findTree;
	  }
	  catch (Exception) {
		return null;
	  }
	}

	#region 按序号列表格式化数据列表
	/// <summary>
	/// 按序号列表格式化数据列表
	/// </summary>
	/// <typeparam name="Data">要格式化的数据类型</typeparam>
	/// <param name="treeList">数据列表</param>
	/// <param name="indexList">序号列表</param>
	/// <param name="format">格式化数据回调函数</param>
	/// <returns></returns>
	#endregion
	public static List<Data> FindFormatDataByIndex<Data>(List<Tree> treeList, List<int> indexList, DataFormatBack<Data> format) {
	  // 判断序号类别
	  if (indexList == null) {
		return null;
	  }
	  var indexCount = indexList.Count;
	  // 初始数据
	  List<Data> valueList = new List<Data>();
	  List<Tree> findList = treeList;
	  try {
		// 根据序号往下寻找数据
		foreach (var index in indexList) {
		  var findItem = findList[index];
		  valueList.Add(format(findItem, index, findList));
		  findList = findItem.Children;
		}
	  }
	  catch (Exception) {
		return null;
	  }
	  return valueList;
	}

	#region 按回调判断取序号列表
	/// <summary>
	/// 按回调判断取序号列表
	/// </summary>
	/// <param name="treeList">数据列表</param>
	/// <param name="format">格式化数据回调函数</param>
	/// <returns></returns>
	#endregion
	public static List<int> FindIndexByFormatEquals(List<Tree> treeList, DataFormatBack<bool> format) {
	  return FindIndexByFormatEquals(treeList, new List<int>(), format);
	}

	#region 按回调判断取序号列表
	/// <summary>
	/// 按回调判断取序号列表
	/// </summary>
	/// <param name="treeList">数据列表</param>
	/// <param name="indexList">序号列表指针</param>
	/// <param name="format">格式化数据回调函数</param>
	/// <returns></returns>
	#endregion
	private static List<int> FindIndexByFormatEquals(List<Tree> treeList, List<int> indexList, DataFormatBack<bool> format) {
	  // 判断节点列表是否为空
	  if (treeList == null) {
		return null;
	  }
	  // 获取节点数量
	  var count = treeList.Count;
	  if (count == 0) {
		return null;
	  }
	  for (int i = 0; i < count; i++) {
		// 循环判断节点内容
		var tree = treeList[i];
		var childIndexList = indexList.GetRange(0, indexList.Count);
		childIndexList.Add(i);
		if (format(tree, i, treeList)) {
		  return childIndexList;
		}
		else {
		  // 如 节点有子节点 则 寻找子节点列表的内容
		  var findChild = FindIndexByFormatEquals(tree.Children, childIndexList, format);
		  if (findChild != null) {
			return findChild;
		  }
		}
	  }
	  return null;
	}

	#region 按格式化的内容列表寻找序号列表
	/// <summary>
	/// 按格式化的内容列表寻找序号列表
	/// </summary>
	/// <typeparam name="Data">要格式化的数据类型</typeparam>
	/// <param name="treeList">数据列表</param>
	/// <param name="valueList">查找的数据列表</param>
	/// <param name="format">格式化数据回调函数</param>
	/// <returns></returns>
	#endregion
	public static List<int> FindIndexByFormatDataEquals<Data>(List<Tree> treeList, List<Data> valueList, DataFormatBack<Data> format) {
	  return FindIndexByFormatDataEquals(treeList, new List<int>(), valueList, format);
	}

	#region 按格式化的内容列表寻找序号列表
	/// <summary>
	/// 按格式化的内容列表寻找序号列表
	/// </summary>
	/// <typeparam name="Data">要格式化的数据类型</typeparam>
	/// <param name="treeList">数据列表</param>
	/// <param name="indexList">序号列表指针</param>
	/// <param name="valueList">查找的数据列表</param>
	/// <param name="format">格式化数据回调函数</param>
	/// <returns></returns>
	#endregion
	private static List<int> FindIndexByFormatDataEquals<Data>(List<Tree> treeList, List<int> indexList, List<Data> valueList, DataFormatBack<Data> format) {
	  // 判断节点列表是否为空
	  if (treeList == null) {
		return null;
	  }
	  // 获取节点数量
	  var count = treeList.Count;
	  if (count == 0) {
		return null;
	  }
	  // 节点阶级
	  var indexCount = indexList.Count;
	  var valueCount = valueList.Count;
	  if (indexCount >= valueCount) {
		return null;
	  }
	  for (int i = 0; i < count; i++) {
		// 循环判断节点内容
		var tree = treeList[i];
		var childIndexList = indexList.GetRange(0, indexCount);
		childIndexList.Add(i);
		if (valueList[indexCount].Equals(format(tree, i, treeList))) {
		  if (indexCount == valueCount - 1) {
			return childIndexList;
		  }
		  else {
			// 如 节点有子节点 则 寻找子节点列表的内容
			var findChild = FindIndexByFormatDataEquals(tree.Children, childIndexList, valueList, format);
			if (findChild != null) {
			  return findChild;
			}
		  }
		}
	  }
	  return null;
	}

	#region 按序号取数据
	/// <summary>
	/// 按序号取数据
	/// </summary>
	/// <param name="treeList">数据列表</param>
	/// <param name="indexList">序号列表</param>
	/// <returns></returns>
	#endregion
	public static List<Tree> FindTreeListByIndex(List<Tree> treeList, List<int> indexList) {
	  return FindFormatDataByIndex(treeList, indexList, (tree, index, list) => {
		return tree;
	  });
	}

	#region 根据序号列表获取数据
	/// <summary>
	/// 根据序号列表获取数据
	/// </summary>
	/// <returns></returns>
	#endregion
	public static List<Tree> FindChildrenByIndex(List<Tree> treeList, List<int> indexList) {
	  // 获取序号信息
	  var indexCount = indexList.Count;
	  // 初始数据
	  List<Tree> findList = treeList;
	  try {
		// 根据序号往下寻找数据
		foreach (var index in indexList) {
		  findList = findList[index].Children;
		}
	  }
	  catch (Exception) {
		return null;
	  }
	  return findList;
	}
  }
}
